home *** CD-ROM | disk | FTP | other *** search
- # include <ingres.h>
- # include <aux.h>
- # include <catalog.h>
- # include <access.h>
- # include <tree.h>
- # include <symbol.h>
- # include <lock.h>
- # include <pv.h>
- # include <func.h>
- # include "qrymod.h"
- # include <sccs.h>
- # include <errors.h>
-
- SCCSID(@(#)d_prot.c 8.3 2/8/85)
-
-
-
- /*
- ** D_PROT -- define protection constraint
- **
- ** A protection constraint as partially defined by the last tree
- ** defined by d_tree is defined.
- **
- ** The stuff that comes through the pipe as parameters is complex.
- ** It comes as a sequence of strings:
- ** # The operation set, already encoded in the parser into a
- ** bit map. If the PRO_RETR permission is set, the PRO_TEST
- ** and PRO_AGGR permissions will also be set.
- ** # The relation name.
- ** # The relation owner.
- ** # The user name. This must be a user name as specified in
- ** the 'users' file, or the keyword 'all', meaning all users.
- ** # The terminal id. Must be a string of the form 'ttyx' or
- ** the keyword 'all'.
- ** # The starting time of day, as minutes-since-midnight.
- ** # The ending time of day.
- ** # The starting day-of-week, with 0 = Sunday.
- ** # The ending dow.
- **
- ** The domain reference set is build automatically from the
- ** target list of the tree. Thus, the target list must exist,
- ** but it is not inserted into the tree. The target list must
- ** be a flat sequence of RESDOM nodes with VAR nodes hanging
- ** of the rhs; also, the VAR nodes must all be for Qt.qt_resvar.
- ** If there is no target list on the tree, the set of all var-
- ** iables is assumed.
- **
- ** The relstat field in the relation relation is updated to
- ** reflect any changes.
- **
- ** It only makes sense for the DBA to execute this command.
- **
- ** If there is one of the special cases
- ** permit all to all
- ** permit retrieve to all
- ** it is caught, and the effect is achieved by diddling
- ** relstat bits instead of inserting into the protect catalog.
- **
- ** Parameters:
- ** none
- **
- ** Returns:
- ** none
- **
- ** Side Effects:
- ** Activity in 'protect' and 'relation' catalogs.
- **
- ** Trace Flags:
- ** 59
- */
-
- extern struct admin Admin;
- extern DESC Prodes;
- extern DESC Reldes;
-
- extern d_prot(), null_fn();
- extern short tTqm[80];
-
- struct fn_def DefProFn =
- {
- "DPROT",
- d_prot,
- null_fn,
- null_fn,
- NULL,
- 0,
- tTqm,
- 80,
- 'Q',
- 0
- };
-
- d_prot(pc, pv)
- int pc;
- PARM *pv;
- {
- struct protect protup;
- struct tup_id protid;
- struct protect prokey;
- struct protect proxtup;
- char buf[30];
- char ubuf[MAXLINE + 1];
- register int i;
- auto short ix;
- int treeid;
- register QTREE *t;
- QTREE *root;
- register char *p;
- struct relation reltup;
- struct relation relkey;
- struct tup_id reltid;
- int relstat;
- int all_pro;
-
- /*
- ** Fill in the protection tuple with the information
- ** from the parser, validating as we go.
- **
- ** Also, determine if we have a PERMIT xx to ALL
- ** with no further qualification case. The variable
- ** 'all_pro' is set to reflect this.
- */
-
- clr_tuple(&Prodes, &protup);
- all_pro = TRUE;
-
- /* read operation set */
- if (pv->pv_type != PV_INT)
- syserr("d_prot: opset");
- protup.proopset = pv->pv_val.pv_int;
- if ((protup.proopset & PRO_RETR) != 0)
- protup.proopset |= PRO_TEST | PRO_AGGR;
- pv++;
-
- /* read relation name */
- if (pv->pv_type != PV_STR)
- syserr("d_prot: relid");
- pmove(pv->pv_val.pv_str, protup.prorelid, MAXNAME, ' ');
- pv++;
-
- /* read relation owner */
- if (pv->pv_type != PV_STR)
- syserr("d_prot: relid");
- bmove(pv->pv_val.pv_str, protup.prorelown, 2);
- pv++;
-
- /* read user name */
- if (pv->pv_type != PV_STR)
- syserr("d_prot: user");
- if (sequal(pv->pv_val.pv_str, "all"))
- bmove(" ", protup.prouser, 2);
- else
- {
- /* look up user in 'users' file */
- if (getnuser(pv->pv_val.pv_str, ubuf))
- qmerror(BADUSRNAME, -1, Qt.qt_resvar, pv->pv_val.pv_str, 0);
- for (p = ubuf; *p != ':' && *p != 0; p++)
- continue;
- bmove(++p, protup.prouser, 2);
- if (p[0] == ':' || p[1] == ':' || p[2] != ':')
- syserr("d_prot: users %s", ubuf);
- all_pro = FALSE;
- }
- pv++;
-
- /* read terminal id */
- if (pv->pv_type != PV_STR)
- syserr("d_prot: user");
- if (sequal(pv->pv_val.pv_str, "all"))
- pmove("", protup.proterm, sizeof protup.proterm, ' ');
- else
- {
- pmove(pv->pv_val.pv_str, protup.proterm, sizeof protup.proterm, ' ');
- if (!isttyname(pv->pv_val.pv_str))
- qmerror(BADTERM, -1, Qt.qt_resvar, pv->pv_val.pv_str, 0);
- all_pro = FALSE;
- }
- pv++;
-
- /* read starting time of day */
- if (pv->pv_type != PV_INT)
- syserr("d_prot: btod");
- protup.protodbgn = pv->pv_val.pv_int;
- if (pv->pv_val.pv_int > 0)
- all_pro = FALSE;
- pv++;
-
- /* read ending time of day */
- if (pv->pv_type != PV_INT)
- syserr("d_prot: etod");
- protup.protodend = pv->pv_val.pv_int;
- if (pv->pv_val.pv_int < 24 * 60 - 1)
- all_pro = FALSE;
- pv++;
-
- /* read beginning day of week */
- if (pv->pv_type != PV_STR)
- syserr("d_prot: bdow");
- i = cvt_dow(pv->pv_val.pv_str);
- if (i < 0)
- qmerror(BADDOW, -1, Qt.qt_resvar, pv->pv_val.pv_str, 0); /* bad dow */
- protup.prodowbgn = i;
- if (i > 0)
- all_pro = FALSE;
- pv++;
-
- /* read ending day of week */
- if (pv->pv_type != PV_STR)
- syserr("d_prot: edow");
- i = cvt_dow(pv->pv_val.pv_str);
- if (i < 0)
- qmerror(BADDOW, -1, Qt.qt_resvar, pv->pv_val.pv_str, 0); /* bad dow */
- protup.prodowend = i;
- if (i < 6)
- all_pro = FALSE;
- pv++;
-
- /*
- ** Check for valid tree:
- ** There must be a tree defined, and all variables
- ** referenced must be owned by the current user; this
- ** is because you could otherwise get at data by
- ** mentioning it in a permit statement; see protect.c
- ** for a better explanation of this.
- */
-
- if (pv->pv_type != PV_QTREE)
- syserr("d_prot: tree");
- root = (QTREE *) pv->pv_val.pv_qtree;
- pv++;
-
- for (i = 0; i < MAXVAR + 1; i++)
- {
- if (Qt.qt_rangev[i].rngvdesc == NULL)
- continue;
- if (!bequal(Qt.qt_rangev[i].rngvdesc->reldum.relowner, Usercode, UCODE_SZ))
- qmerror(OWNEDNOT, -1, i, 0);
- }
-
- /* test for dba */
- if (!bequal(Usercode, Admin.adhdr.adowner, UCODE_SZ))
- qmerror(NOTDBA, -1, Qt.qt_resvar, 0);
-
- /* get domain reference set from target list */
- /* (also, find the TREE node) */
- t = root->left;
- if (t->sym.type == TREE)
- {
- for (i = 0; i < 8; i++)
- protup.prodomset[i] = -1;
- }
- else
- {
- for (i = 0; i < 8; i++)
- protup.prodomset[i] = 0;
- for (; t->sym.type != TREE; t = t->left)
- {
- if (t->right->sym.type != VAR ||
- t->sym.type != RESDOM ||
- t->right->sym.value.sym_var.varno != Qt.qt_resvar)
- syserr("d_prot: garbage tree");
- lsetbit(t->right->sym.value.sym_var.attno, protup.prodomset);
- }
- all_pro = FALSE;
- }
-
- /* trim off the target list, since it isn't used again */
- root->left = t;
-
- /*
- ** Check out the target relation.
- ** We first save the varno of the relation which is
- ** getting the permit stuff. Also, we check to see
- ** that the relation mentioned is a base relation,
- ** and not a view, since that tuple would never do
- ** anything anyway. Finally, we clear the Qt.qt_resvar
- ** so that it does not get output to the tree catalog.
- ** This would result in a 'syserr' when we tried to
- ** read it.
- */
-
- protup.proresvar = Qt.qt_resvar;
- # ifdef xQTR3
- if (Qt.qt_resvar < 0)
- syserr("d_prot: Rv %d", Qt.qt_resvar);
- # endif
- if (bitset(S_VIEW, Qt.qt_rangev[Qt.qt_resvar].rngvdesc->reldum.relstat))
- qmerror(NOTREALREL, -1, Qt.qt_resvar, 0); /* is a view */
-
- /* clear the (unused) Qt.qt_qmode */
- # ifdef xQTR3
- if (Qt.qt_qmode != mdPROT)
- syserr("d_prot: Qt.qt_qmode %d", Qt.qt_qmode);
- # endif
- Qt.qt_qmode = -1;
-
- /*
- ** Check for PERMIT xx to ALL case.
- ** The relstat bits will be adjusted as necessary
- ** to reflect these special cases.
- **
- ** This is actually a little tricky, since we cannot
- ** afford to turn off any permissions. If we already
- ** have some form of PERMIT xx to ALL access, we must
- ** leave it.
- */
-
- relstat = Qt.qt_rangev[Qt.qt_resvar].rngvdesc->reldum.relstat;
- if (all_pro && (protup.proopset & PRO_RETR) != 0)
- {
- if (protup.proopset == -1)
- relstat &= ~S_PROTALL;
- else
- {
- relstat &= ~S_PROTRET;
- if ((protup.proopset & ~(PRO_RETR|PRO_AGGR|PRO_TEST)) != 0)
- {
- /* some special case: still insert prot tuple */
- all_pro = FALSE;
- }
- }
- }
- else
- all_pro = FALSE;
-
- /* see if we are adding any tuples */
- if (!all_pro)
- relstat |= S_PROTUPS;
-
- /*
- ** Change relstat field in relation catalog if changed
- */
-
- if (relstat != Qt.qt_rangev[Qt.qt_resvar].rngvdesc->reldum.relstat)
- {
- opencatalog("relation", OR_WRITE);
- setkey(&Reldes, &relkey, Qt.qt_rangev[Qt.qt_resvar].rngvdesc->reldum.relid, RELID);
- setkey(&Reldes, &relkey, Qt.qt_rangev[Qt.qt_resvar].rngvdesc->reldum.relowner, RELOWNER);
- i = getequal(&Reldes, &relkey, &reltup, &reltid);
- if (i != 0)
- syserr("d_prot: geteq %d", i);
- reltup.relstat = relstat;
- i = replace(&Reldes, &reltid, &reltup, FALSE);
- if (i != 0)
- syserr("d_prot: repl %d", i);
- if (noclose(&Reldes) != 0)
- syserr("d_prot: noclose(rel)");
- }
-
- Qt.qt_resvar = -1;
-
- if (!all_pro)
- {
- /*
- ** Output the created tuple to the protection catalog
- ** after making other internal adjustments and deter-
- ** mining a unique sequence number (with the protect
- ** catalog locked).
- */
-
- if (root->right->sym.type != QLEND)
- protup.protree = puttree(root, protup.prorelid, protup.prorelown, mdPROT);
- else
- protup.protree = -1;
-
- /* compute unique permission id */
- opencatalog("protect", OR_WRITE);
- setrll(A_SLP, Prodes.reltid.ltid, M_EXCL);
- setkey(&Prodes, &prokey, protup.prorelid, PRORELID);
- setkey(&Prodes, &prokey, protup.prorelown, PRORELOWN);
- for (ix = 2; ; ix++)
- {
- setkey(&Prodes, &prokey, &ix, PROPERMID);
- i = getequal(&Prodes, &prokey, &proxtup, &protid);
- if (i < 0)
- syserr("d_prot: geteq");
- else if (i > 0)
- break;
- }
- protup.propermid = ix;
-
- /* do actual insert */
- i = insert(&Prodes, &protid, &protup, FALSE);
- if (i < 0)
- syserr("d_prot: insert");
- if (noclose(&Prodes) != 0)
- syserr("d_prot: noclose(pro)");
-
- /* clear the lock */
- unlrl(Prodes.reltid.ltid);
- }
- }
- /*
- ** CVT_DOW -- convert day of week
- **
- ** Converts the day of the week from string form to a number.
- **
- ** Parameters:
- ** sdow -- dow in string form.
- **
- ** Returns:
- ** 0 -> 6 -- the encoded day of the week.
- ** -1 -- error.
- **
- ** Side Effects:
- ** none
- **
- ** Defines:
- ** Dowlist -- a mapping from day of week to number.
- ** cvt_dow
- **
- ** Called By:
- ** d_prot
- */
-
- struct downame
- {
- char *dow_name;
- int dow_num;
- };
-
- struct downame Dowlist[] =
- {
- "sun", 0,
- "sunday", 0,
- "mon", 1,
- "monday", 1,
- "tue", 2,
- "tues", 2,
- "tuesday", 2,
- "wed", 3,
- "wednesday", 3,
- "thu", 4,
- "thurs", 4,
- "thursday", 4,
- "fri", 5,
- "friday", 5,
- "sat", 6,
- "saturday", 6,
- NULL
- };
-
- cvt_dow(sdow)
- char *sdow;
- {
- register struct downame *d;
- register char *s;
-
- s = sdow;
-
- for (d = Dowlist; d->dow_name != NULL; d++)
- if (sequal(d->dow_name, s))
- return (d->dow_num);
- return (-1);
- }
- /*
- ** ISTTYNAME -- "is a legal terminal name" predicate
- **
- ** Returns TRUE if the argument is a legal terminal name,
- ** otherwise FALSE.
- **
- ** It may make sense to have this routine check if the given
- ** file name really exists.
- **
- ** WARNING:
- ** This routine may be installation-dependent!
- **
- ** Parameters:
- ** n -- the name to check.
- **
- ** Returns:
- ** TRUE -- n is a legal tty name at this installation.
- ** FALSE -- otherwise.
- **
- ** Side Effects:
- ** none
- **
- ** History:
- ** 8/1/79 (eric) -- written.
- */
-
-
- isttyname(n)
- register char *n;
- {
- return (sequal(n, "console") || bequal(n, "tty", 3));
- }
-